#ifndef _BEncode_H
#define _BEncode_H

#include <stdio.h>
#include <stdlib.h>

#include <string>
#include <list>
#include <map>
using namespace std;

class BItem
{
public:
    BItem()
	{
		m_next = nullptr;
	}
    virtual ~BItem()
	{
		delete m_next;
	};
	BItem* getNext()
	{
		return m_next;
	}
	void setNext(BItem* n)
	{
		m_next = n;
	}
	virtual void print() {};

private:
	BItem* m_next;
};

class BNumber : public BItem
{
public:
	BNumber(int n)
	{
		m_number = n;
	}
	~BNumber()
	{

	}
	int get()
	{
		return m_number;
	}

	void print()
	{
		printf("%d", m_number);
	}

private:
	int m_number;
};

class BString : public BItem
{
public:
    BString(string s)
    {
        m_text = s;
    }
    ~BString()
    {

    }
    string get()
    {
        return m_text;
    }
    void print()
    {
		if (m_text.size() > 200)
		{
			if ((m_text.size() % 20) != 0)
			{
				printf("err");
			}
			else
			{
				int length = m_text.size() / 20;
				for (size_t i = 0; i < length; i++)
				{
					for (size_t j = 0; j < 20; j++)
					{
						unsigned char c = m_text[i * 20 + j];
						printf("%.2X", c);
					}
					printf(" ");
				}
			}
		}
		else
		{
			printf("\"%s\"", m_text.c_str());
		}
    }
private:
    string m_text;
};

class BList : public BItem
{
public:
    BList()
    {
		m_content = nullptr;
    }
    ~BList()
    {

    }
	void print()
	{
		BItem* p = m_content;
		bool isFirst = true;

		printf("[");
		while (p != nullptr)
		{
			if (isFirst)
			{
				isFirst = false;
			}
			else
			{
				printf(",");
			}
			p->print();
			p = p->getNext();
		}
		printf("]");
	}

public:
	BItem* m_content;
};

class Pairs : public BItem
{
public:
	Pairs()
	{
		m_key = nullptr;
		m_value = nullptr;
	};

	~Pairs()
	{
		if (m_key)
		{
			delete m_key;
		}
		if (m_value)
		{
			delete m_value;
		}
	};

	void print()
	{
		m_key->print();
		printf(":");
		m_value->print();
	}

public:
	BItem* m_key;
	BItem* m_value;
};

class BDic : public BItem
{
public:
	BDic()
    {
		m_content = nullptr;
    }
    ~BDic()
    {

    }

	void print()
	{
		BItem* p = m_content;
		bool isFirst = true;

		printf("{");
		while (p != nullptr)
		{
			if (isFirst)
			{
				isFirst = false;
			}
			else
			{
				printf(",");
			}
			p->print();
			p = p->getNext();
		}
		printf("}");
	}

public:
	Pairs* m_content;
};

class BEncode
{
public:
	BEncode();
	~BEncode();
	
	BItem* load(const char* data, int len);
	void print();
	
private:
    int findChar(const char* data, char c);
	int parserNumber(BItem*& parent, const char* data);
	int parserString(BItem*& parent, const char* data);
	int parserlist(BItem*& parent, const char* data);
	int parserdic(BItem*& parent, const char* data);

private:
	BItem* m_head;
};

#endif
